package cn.bossfriday.boot;

import cn.bossfriday.common.common.SystemConfig;
import cn.bossfriday.common.plugin.PluginSpringContext;
import cn.bossfriday.im.common.PluginBootstrap;
import cn.bossfriday.im.common.conf.ConfigurationAllLoader;
import cn.bossfriday.im.common.enums.BootstrapBanners;
import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;

import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import static cn.bossfriday.im.common.constant.ImConstant.BASE_PACKAGE_NAME;

/**
 * Bootstrap
 *
 * @author chenx
 */
@Slf4j
public class Bootstrap {

    /**
     * 统一启动
     */
    public static void main(String[] args) {
        try {
            long begin = System.currentTimeMillis();
            PluginSpringContext.initialize(BASE_PACKAGE_NAME);
            List<PluginBootstrap> pluginBootstraps = getPluginBootstraps();
            SystemConfig systemConfig = ConfigurationAllLoader.getInstance().getSystemConfig();

            // startup
            pluginBootstraps.forEach(plugin -> plugin.startup(systemConfig));
            long time = System.currentTimeMillis() - begin;
            log.info("All Services Startup Done, time {}", time);
            BootstrapBanners.START.printBanner(log);

            // shutdown
            Runtime.getRuntime().addShutdownHook(new Thread(() -> pluginBootstraps.forEach(PluginBootstrap::shutdown)));
        } catch (Exception ex) {
            log.error("Bootstrap error!", ex);
            BootstrapBanners.FAIL.printBanner(log);
            System.exit(0);
        }
    }


    /**
     * getPlugins
     *
     * @return
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    private static List<PluginBootstrap> getPluginBootstraps() throws NoSuchMethodException,
            InvocationTargetException,
            InstantiationException,
            IllegalAccessException {
        List<PluginBootstrap> pluginBootstraps = new LinkedList<>();
        Set<Class<? extends PluginBootstrap>> pluginClassSet = new Reflections(BASE_PACKAGE_NAME).getSubTypesOf(PluginBootstrap.class);
        for (Class<? extends PluginBootstrap> pluginClass : pluginClassSet) {
            PluginBootstrap instance = pluginClass.getDeclaredConstructor().newInstance();
            pluginBootstraps.add(instance);
        }

        return pluginBootstraps;
    }
}
